/**
 * $Id: SparqlBuilder.java 9 2011-10-05 14:12:06Z adriftrock@gmail.com $
 */

package com.swehr.server.daos.impl;

import com.swehr.utils.StringUtil;

/**
 * @author Rock Huang
 * @version 0.1
 */
class SparqlBuilder {
    private SparqlBuilder() {}

    /**
     * replace string holder in the give sparql command.
     *
     * @param c   A full string needs to replace some string holder.
     * @param s   A string holder which will be replaced.
     * @param lbl A label as a predicate or data type property.
     * @param vo  An old value which will be updated.
     * @param v   An new value which will use to update.
     * @param seg To indicate whether needs to put a separator.
     * @param changed Is data changed or unchanged
     * @return To tell next triple whether needs to put a semicolon.
     */
    public static boolean replace(StringBuffer c, String s, String lbl, String vo,
                            String v, boolean seg, boolean changed) {
        int p = c.indexOf(s);
        c.replace(p, p + s.length(), triple(lbl, vo, seg, changed));
        p = c.indexOf(s);
        c.replace(p, p + s.length(), triple(lbl, v, seg, changed));
        return seg || changed;
    }

    public static boolean replace(StringBuffer c, String s, String lbl, String ov, String v, boolean seg) {
        return replace(c, s, lbl, ov, v, seg, isModified(v, ov));
    }

    public static boolean replaceOrg(StringBuffer c, String ot, String t, String ov, String v, boolean change) {
        if (StringUtil.isEmptyOrNull(ov, v)) {
            replace(c, "@org", "");
            replace(c, "@org", "");
            return change;
        }

        if(ov == null) ov = "0";
        ot = convertFirstLetter(ot);
        t = convertFirstLetter(t);
        ov = wrapOrg(ov);
        v = wrapOrg(v);

        if (change) {
            replace(c, "@org", triple("is"+ot+"Of", ov, change, isModified(v, ov)));
            replace(c, "@org", triple("is"+t+"Of", v, change, isModified(v, ov)));
            return true;
        } else {
            return replace(c, "@org", "is"+ot+"Of", ov, v, change);
        }
    }

    public static String convertFirstLetter(String s) {
        char oldChar = s.charAt(0);
        char newChar = Character.toUpperCase(oldChar);
        return s.replace(oldChar, newChar);
    }

    public static void replace(StringBuffer c, String s, String v) {
        int p = c.indexOf(s);
        c.replace(p, p + s.length(), v);
    }

    public static void replaceLast(StringBuffer c, String s, String v)  {
        int p = c.lastIndexOf(s);
        System.out.println(p);
        c.replace(p, p + s.length(), v);
    }

    public static void replaceAll(StringBuffer c, String s, String v) {
        int p = c.indexOf(s);
        while (p != -1) {
            c.replace(p, p + s.length(), v);
            p = c.indexOf(s);
        }
    }

    public static boolean isModified(String s, String sOld) {
        return !StringUtil.isEmptyOrNull(s) && !s.equals(sOld);
    }

    public static String triple(String lbl, String v, boolean seg, boolean changed) {
        if (!changed) return "";

        if (lbl.equalsIgnoreCase("rdf:type")) {
            v = "ehr:" + convertFirstLetter(v);
        } else if (lbl.startsWith("is") && lbl.endsWith("Of") && !StringUtil.isEmptyOrNull(v)) {
            lbl = "ehr:" + lbl;
        } else if (lbl.endsWith("@datetime")) {
            lbl = "ehr:" + lbl.substring(0, lbl.indexOf('@'));
            v = "\"" + v + "\"" + "^^xsd:dateTime";
        } else if (v.trim().startsWith("<http:")) {
            lbl = "ehr:" + lbl;
        } else {
            lbl = "ehr:" + lbl;
            v = "\"" + v + "\"";
        }

        if (seg) return " . ?o " + lbl + " " + v;
        else return "?o " + lbl + " " + v;
    }

    public static String wrapOrg(String localName) {
        return wrap(localName, Const.URI_ORG);
    }

    public static String wrapPsn(String localName) {
        return wrap(localName, Const.URI_PSN);
    }

    public static String wrapPos(String localName) {
        return wrap(localName, Const.URI_POS);
    }

    public static String wrap(String localName, String constUri) {
        if (localName.startsWith("<") && localName.endsWith(">")) {
            return localName;
        }
        if (localName.startsWith("http")) {
            return " <" + localName + ">";
        }

        StringBuffer uri = new StringBuffer(constUri);
        replace(uri, "@id", localName);
        return " " + uri.toString();
    }

    public static String wrapUriPrefix(String uri) {
        if (!uri.startsWith("http://")) {
            return "http://" + uri;
        }
        return uri;
    }

    public static String changeSuffix(String uri) {
        if (uri.endsWith("/")) {
            return uri.substring(0, uri.length() - 1);
        } else {
            return uri + "/";
        }
    }

}
